# LDA 分类 iris 分析例子
import matplotlib.pyplot as plt
from sklearn import datasets
import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

from sklearn import metrics
import pandas
import seaborn as sn

### 加载数据  ########################################
iris = datasets.load_iris()
# print(iris)
X = iris.data
y = iris.target
target_names = iris.target_names
# print(X)
# print(y)

### 数据分析 ##########################################
print(X.shape, y.shape)
z = y.reshape(-1, 1)
data = np.hstack((X, z))
data = pandas.DataFrame(data)
data.rename(columns={0: "萼片长", 1: "萼片宽", 2: "花瓣长", 3: "花瓣宽", 4: "种类"}, inplace=True)
# data.head()
kind_dict = {0: "山鸢尾", 1: "杂色鸢尾", 2: "维吉尼亚鸢尾"}
data["种类"] = data["种类"].map(kind_dict)
sn.set_style('white', {'font.sans-serif': ['simhei', 'Arial']})
sn.pairplot(data, hue="种类")   #画出成对图



### 调用LDA 求解 ###########################
lda = LDA(n_components=2)   # 采用二维投影，也可以设置其他维
lda.fit(X, y)

### 计算混淆矩阵与准确率 ####这里没有分开 训练集与测试集######################
y_ = lda.predict(X)  # 生成预测结果
cm = metrics.confusion_matrix(y, y_)
print(cm)
print(metrics.accuracy_score(y, y_))
print(metrics.recall_score(y, y_, average='macro'))
print(metrics.precision_score(y, y_, average='macro'))
print(metrics.f1_score(y, y_, average='macro'))

report = metrics.classification_report(y, y_)##
# print('输出分类报告：', report)
print(report)


### 2维投影画图 计算全部数据投影之后的3个类别的中心坐标 ###################
X_r2 = lda.transform(X)  # 数据投影（转换）

mu = np.zeros((3, 2))   # 3个类别的中心
for i in range(3):
    mu[i] = np.average(X_r2[y == i], axis=0)  # 求出中心坐标
print(mu)

#####绘图
plt.figure()     # 新开一图
### 画出数据投影之后的分类曲线
x1_min, x1_max = X_r2[:, 0].min() - 1, X_r2[:, 0].max() + 1
x2_min, x2_max = X_r2[:, 1].min() - 1, X_r2[:, 1].max() + 1
resolution = 0.1
# 绘制网格
xx, yy = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution))


# 计算xx与yy中每对坐标（x,y)所对应的分类z
zz = np.zeros((3, *xx.shape))
for i in range(3):
    zz[i, :, :] = (xx - mu[i, 0]) ** 2 + (yy - mu[i, 1]) ** 2
zz = np.argmin(zz, 0)
print(zz.shape)
####################

plt.contourf(xx, yy, zz, alpha=0.3)

###画出每一类别的数据散列表，不同数据用不同颜色
colors = ['navy', 'turquoise', 'darkorange']
for color, i, target_name in zip(colors, [0, 1, 2], target_names):
    plt.scatter(X_r2[y == i, 0], X_r2[y == i, 1], alpha=0.8, color=color,
                label=target_name)

plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('LDA of IRIS dataset')

### 画出3个类别中线坐标
plt.scatter(mu[:, 0], mu[:, 1], c='red', marker='s', s=40)
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负
plt.show()
